    //
//  OAuthController.m
//  JustPhotoIt
//
//  Created by mac on 11-4-18.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "OAuthController.h"
#import "OAuthEngine.h"
#import "GlobalCore.h"

@interface NSString (OAuth)
- (BOOL) oauth_isNumeric;
@end

@implementation NSString (OAuth)
- (BOOL) oauth_isNumeric {
	const char				*raw = (const char *) [self UTF8String];
	
	for (int i = 0; i < strlen(raw); i++) {
		if (raw[i] < '0' || raw[i] > '9') return NO;
	}
	return YES;
}
@end

@interface DummyClassForProvidingSetDataDetectorTypesMethod

- (void) setDataDetectorTypes: (int) types;
- (void) setDetectsPhoneNumbers: (BOOL) detects;
@end


@implementation OAuthController

@synthesize engine = _engine, delegate = _delegate, navigationBar = _navBar,orientation = _orientation;

// The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization.
    }
    return self;
}
*/


// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void) loadView {
	[super loadView];
	self.view = [[[UIView alloc] initWithFrame: ApplicationFrame(self.orientation)] autorelease];
	_navBar = [[[UINavigationBar alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width, 44)] autorelease];
	
	_navBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
	self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	
	CGRect frame = ApplicationFrame(self.orientation);
	frame.origin.y = 44;
	frame.size.height -= 44;
	_webView = [[UIWebView alloc] initWithFrame: ApplicationFrame(self.orientation)];
	_webView.alpha = 0.0;
	_webView.delegate = self;
	//_webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	if ([_webView respondsToSelector: @selector(setDetectsPhoneNumbers:)]) 
		[(id) _webView setDetectsPhoneNumbers: NO];
	if ([_webView respondsToSelector: @selector(setDataDetectorTypes:)]) 
		[(id) _webView setDataDetectorTypes: 0];
	
	NSURLRequest *request = _engine.authorizeURLRequest;
	[_webView loadRequest: request];
	
	[self.view addSubview: _webView];
	[self.view addSubview: _navBar];
	
	_blockerView = [[[UIView alloc] initWithFrame: CGRectMake(0, 0, 200, 60)] autorelease];
	_blockerView.backgroundColor = [UIColor colorWithWhite: 0.0 alpha: 0.8];
	_blockerView.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
	_blockerView.alpha = 0.0;
	_blockerView.clipsToBounds = YES;
	
//	if ([_blockerView.layer respondsToSelector: @selector(setCornerRadius:)])
//		[(id) _blockerView.layer setCornerRadius: 10];
	
	UILabel *label = [[[UILabel alloc] initWithFrame: CGRectMake(0, 5, _blockerView.bounds.size.width, 15)] autorelease];
	label.text = NSLocalizedString(@"Please Wait…", nil);
	label.backgroundColor = [UIColor clearColor];
	label.textColor = [UIColor whiteColor];
	label.textAlignment = UITextAlignmentCenter;
	label.font = [UIFont boldSystemFontOfSize: 15];
	[_blockerView addSubview: label];
	
	UIActivityIndicatorView *spinner = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhite] autorelease];
	
	spinner.center = CGPointMake(_blockerView.bounds.size.width / 2, _blockerView.bounds.size.height / 2 + 10);
	[_blockerView addSubview: spinner];
	[self.view addSubview: _blockerView];
	[spinner startAnimating];
	
	UINavigationItem *navItem = [[[UINavigationItem alloc] initWithTitle: NSLocalizedString(@"Sina Weibo Info", nil)] autorelease];
	navItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemCancel target: self action: @selector(cancel:)] autorelease];
	
	[_navBar pushNavigationItem: navItem animated: NO];
	[self locateAuthPinInWebView: nil];
}

- (NSString *) locateAuthPinInWebView: (UIWebView *) webView {
	NSString *js = @"var d = document.getElementById('oauth-pin'); if (d == null) d = document.getElementById('oauth_pin'); if (d) d = d.innerHTML; if (d == null) {var r = new RegExp('\\\\s[0-9]+\\\\s'); d = r.exec(document.body.innerHTML); if (d.length > 0) d = d[0];} d.replace(/^\\s*/, '').replace(/\\s*$/, ''); d;";
	NSString *pin = [webView stringByEvaluatingJavaScriptFromString: js];
	
	if (pin.length > 0) return pin;
	
	NSString *html = [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerText"];
	NSLog(@"html:%@", [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerHTML"]);
	
	if (html.length == 0) return nil;
	
	const char			*rawHTML = (const char *) [html UTF8String];
	int					length = strlen(rawHTML), chunkLength = 0;
	
	for (int i = 0; i < length; i++) {
		if (rawHTML[i] < '0' || rawHTML[i] > '9') {
			if (chunkLength == 6) {
				char				*buffer = (char *) malloc(chunkLength + 1);
				
				memmove(buffer, &rawHTML[i - chunkLength], chunkLength);
				buffer[chunkLength] = 0;
				
				pin = [NSString stringWithUTF8String: buffer];
				free(buffer);
				return pin;
			}
			chunkLength = 0;
		} else
			chunkLength++;
	}
	
	return nil;
}

- (void) webViewDidStartLoad: (UIWebView *) webView {
	//[_activityIndicator startAnimating];
	_loading = YES;
	[UIView beginAnimations: nil context: nil];
	_blockerView.alpha = 1.0;
	[UIView commitAnimations];
}

- (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *) request navigationType: (UIWebViewNavigationType) navigationType {
	NSData				*data = [request HTTPBody];
	char				*raw = data ? (char *) [data bytes] : "";
	
	if (raw && strstr(raw, "cancel=")) {
		[self denied];
		return NO;
	}
	if (navigationType != UIWebViewNavigationTypeOther) _webView.alpha = 0.1;
	return YES;
}

- (void) webViewDidFinishLoad: (UIWebView *) webView {
	NSString					*authPin = [self locateAuthPinInWebView: webView];
	
	if (authPin.length) {
		[self gotPin: authPin];
		return;
	}
	/*
	 _loading = NO;
	 //[self performInjection];
	 if (_firstLoad) {
	 //[_webView performSelector: @selector(stringByEvaluatingJavaScriptFromString:) withObject: @"window.scrollBy(0,200)" afterDelay: 0];
	 _firstLoad = NO;
	 } else {
	 NSString					*authPin = [self locateAuthPinInWebView: webView];
	 
	 if (authPin.length) {
	 [self gotPin: authPin];
	 return;
	 }
	 
	 NSString					*formCount = [webView stringByEvaluatingJavaScriptFromString: @"document.forms.length"];
	 
	 if ([formCount isEqualToString: @"0"]) {
	 [self showPinCopyPrompt];
	 }
	 }
	 
	 */
	
	[UIView beginAnimations: nil context: nil];
	_blockerView.alpha = 0.0;
	[UIView commitAnimations];
	
	if ([_webView isLoading]) {
		_webView.alpha = 0.0;
	} else {
		_webView.alpha = 1.0;
	}
}


+ (OAuthController *) controllerToEnterCredentialsWithEngine: (OAuthEngine *) engine delegate: (id <OAuthControllerDelegate>) delegate {
	NSLog(@"%s",__FUNCTION__);
	return [OAuthController controllerToEnterCredentialsWithEngine: engine delegate: delegate forOrientation: UIInterfaceOrientationPortrait];
}

+ (OAuthController *) controllerToEnterCredentialsWithEngine: (OAuthEngine *) engine delegate: (id <OAuthControllerDelegate>) delegate forOrientation: (UIInterfaceOrientation)theOrientation {
	NSLog(@"%s",__FUNCTION__);
	if (![self credentialEntryRequiredWithEngine: engine]) 
		return nil;			//not needed
	
	OAuthController *controller = [[[OAuthController alloc] initWithEngine: engine andOrientation: theOrientation] autorelease];
	
	controller.delegate = delegate;
	return controller;
}

+ (BOOL) credentialEntryRequiredWithEngine: (OAuthEngine *) engine {
	NSLog(@"%s",__FUNCTION__);
	return ![engine isAuthorized];
}

- (id) initWithEngine: (OAuthEngine *) engine andOrientation:(UIInterfaceOrientation)theOrientation {
	NSLog(@"%s",__FUNCTION__);
	if (self = [super init]) {
		self.engine = engine;
		if (!engine.OAuthSetup) [_engine requestRequestToken];
		self.orientation = theOrientation;
		_firstLoad = YES;
		
		
		//[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pasteboardChanged:) name: UIPasteboardChangedNotification object: nil];
	}
	return self;
}

#pragma mark Actions
- (void) denied {
	NSLog(@"%s",__FUNCTION__);
	if ([_delegate respondsToSelector: @selector(OAuthControllerFailed:)]) 
		[_delegate OAuthControllerFailed: self];
	[self performSelector: @selector(dismissModalViewControllerAnimated:) withObject: (id) kCFBooleanTrue afterDelay: 1.0];
}

- (void) gotPin: (NSString *) pin {
	NSLog(@"%s",__FUNCTION__);
	_engine.pin = pin;
	[_engine requestAccessToken];
	
	if ([_delegate respondsToSelector: @selector(OAuthController:authenticatedWithUsername:)]) 
		[_delegate OAuthController: self authenticatedWithUsername: _engine.username];
	
	[self performSelector: @selector(dismissModalViewControllerAnimated:) withObject: (id) kCFBooleanTrue afterDelay: 1.0];
}

- (void) cancel: (id) sender {
	NSLog(@"%s",__FUNCTION__);
	if ([_delegate respondsToSelector: @selector(OAuthControllerCanceled:)]) 
		[_delegate OAuthControllerCanceled: self];
	[self performSelector: @selector(dismissModalViewControllerAnimated:) withObject: (id) kCFBooleanTrue afterDelay: 0.0];
}


/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
*/

/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations.
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void) dealloc {
	
	[[NSNotificationCenter defaultCenter] removeObserver: self];
	_webView.delegate = nil;
	[_webView loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: @""]]];
	[_webView release];
	
	self.view = nil;
	self.engine = nil;
	[super dealloc];
}


@end
